From 964295f6d23e16a837310c365dc4e4bf1865eddf Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Tue, 8 Apr 2008 17:01:23 +0000 Subject: [PATCH] Applied patch from Jan Heller that improves logic of go_fishing code in babl-fish.c. The current code searches list of all fishes while looking for suitable preexistent BABL_FISH_PATH instance. The new code only searches relevant part of database's hash table. Further, the current code searches for fish path every time such a babl fish is requested, even though the same fish path has been requested before and not found. The new code creates dummy BABL_FISH instance with appropriate source/destination formats and inserts it into the fish database to indicate that fish path has been searched for and not found. * babl/babl-fish.c: (find_fish_path), (find_memcpy_fish), (babl_fish_get_id), (babl_fish): * babl/babl-fish-path.c: (babl_fish_path): * babl/babl-fish-reference.c: (babl_fish_reference): * babl/babl-fish-simple.c: (babl_fish_simple): * babl/babl-internal.h: svn path=/trunk/; revision=304 --- ChangeLog | 20 ++++ babl/babl-fish-path.c | 13 +- babl/babl-fish-reference.c | 2 +- babl/babl-fish-simple.c | 3 +- babl/babl-fish.c | 238 +++++++++++++++++++++++++++---------- babl/babl-internal.h | 2 + 6 files changed, 204 insertions(+), 74 deletions(-) diff --git a/ChangeLog b/ChangeLog index 550b4e9..ccb2a20 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2008-04-08 Øyvind Kolås + + Applied patch from Jan Heller that improves logic of go_fishing code + in babl-fish.c. The current code searches list of all fishes while + looking for suitable preexistent BABL_FISH_PATH instance. The new code + only searches relevant part of database's hash table. Further, the + current code searches for fish path every time such a babl fish is + requested, even though the same fish path has been requested before + and not found. The new code creates dummy BABL_FISH instance with + appropriate source/destination formats and inserts it into the fish + database to indicate that fish path has been searched for and not + found. + + * babl/babl-fish.c: (find_fish_path), (find_memcpy_fish), + (babl_fish_get_id), (babl_fish): + * babl/babl-fish-path.c: (babl_fish_path): + * babl/babl-fish-reference.c: (babl_fish_reference): + * babl/babl-fish-simple.c: (babl_fish_simple): + * babl/babl-internal.h: + 2008-04-06 Sven Neumann * acinclude.m4: new file defining BABL_DETECT_CFLAGS() macro. diff --git a/babl/babl-fish-path.c b/babl/babl-fish-path.c index a0a8582..2380b93 100644 --- a/babl/babl-fish-path.c +++ b/babl/babl-fish-path.c @@ -193,9 +193,10 @@ Babl * babl_fish_path (const Babl *source, const Babl *destination) { - Babl *babl = NULL; - char *name = create_name (source, destination, 1); + Babl *babl = NULL; + char *name; + name = create_name (source, destination, 1); babl = babl_db_exist_by_name (babl_fish_db (), name); if (babl) { @@ -205,17 +206,11 @@ babl_fish_path (const Babl *source, return babl; } - babl_assert (BABL_IS_BABL (source)); - babl_assert (BABL_IS_BABL (destination)); - - babl_assert (source->class_type == BABL_FORMAT); - babl_assert (destination->class_type == BABL_FORMAT); - babl = babl_calloc (1, sizeof (BablFishPath) + strlen (name) + 1); babl->class_type = BABL_FISH_PATH; - babl->instance.id = 0; + babl->instance.id = babl_fish_get_id (source, destination); babl->instance.name = ((char *) babl) + sizeof (BablFishPath); strcpy (babl->instance.name, name); babl->fish.source = source; diff --git a/babl/babl-fish-reference.c b/babl/babl-fish-reference.c index bf1bc80..c62a0a6 100644 --- a/babl/babl-fish-reference.c +++ b/babl/babl-fish-reference.c @@ -69,7 +69,7 @@ babl_fish_reference (const Babl *source, babl = babl_malloc (sizeof (BablFishReference) + strlen (name) + 1); babl->class_type = BABL_FISH_REFERENCE; - babl->instance.id = 0; + babl->instance.id = babl_fish_get_id (source, destination); babl->instance.name = ((char *) babl) + sizeof (BablFishReference); strcpy (babl->instance.name, name); babl->fish.source = source; diff --git a/babl/babl-fish-simple.c b/babl/babl-fish-simple.c index 6c933d8..42fcd86 100644 --- a/babl/babl-fish-simple.c +++ b/babl/babl-fish-simple.c @@ -33,7 +33,6 @@ babl_fish_simple (BablConversion *conversion) babl_assert (BABL_IS_BABL (conversion)); name = create_name (conversion); - babl = babl_db_exist_by_name (babl_fish_db (), name); if (babl) { @@ -46,7 +45,7 @@ babl_fish_simple (BablConversion *conversion) babl = babl_malloc (sizeof (BablFishSimple) + strlen (name) + 1); babl->class_type = BABL_FISH_SIMPLE; - babl->instance.id = 0; + babl->instance.id = babl_fish_get_id (conversion->source, conversion->destination); babl->instance.name = ((char *) babl) + sizeof (BablFishSimple); strcpy (babl->instance.name, name); babl->fish.source = conversion->source; diff --git a/babl/babl-fish.c b/babl/babl-fish.c index 7f22ebf..a14fac2 100644 --- a/babl/babl-fish.c +++ b/babl/babl-fish.c @@ -20,6 +20,87 @@ #include #include +typedef struct _BablFindFish BablFindFish; + +typedef struct _BablFindFish +{ + Babl *fish_path; + Babl *fish_ref; + Babl *fish_fish; + int fishes; + const Babl *source; + const Babl *destination; +} _BablFishFish; + + +static int +match_conversion (Babl *conversion, + void *inout); + +static int +find_fish_path (Babl *item, + void *data); + +static int +find_memcpy_fish (Babl *item, + void *data); + +static int +each_babl_fish_destroy (Babl *babl, + void *data); + + +/* ====================================== */ + + +static int +find_fish_path (Babl *item, + void *data) +{ + BablFindFish *ffish = (BablFindFish *) data; + if ((item->fish.source == ffish->source) && + (item->fish.destination == ffish->destination)) + { + if (item->instance.class_type == BABL_FISH_REFERENCE) + { + ffish->fish_ref = item; + ffish->fishes++; + } + else if (item->instance.class_type == BABL_FISH_PATH) + { + ffish->fish_path = item; + ffish->fishes++; + } + else if (item->instance.class_type == BABL_FISH) + { + ffish->fish_fish = item; + ffish->fishes++; + } + if (ffish->fishes == 3) + return 1; + } + + return 0; +} + +static int +find_memcpy_fish (Babl *item, + void *data) +{ + BablFindFish *ffish = (BablFindFish *) data; + if ((item->fish.source == ffish->source) && + (item->fish.destination == ffish->destination)) + { + if ((item->fish.source == item->fish.destination) && + (item->instance.class_type == BABL_FISH_REFERENCE)) + { + ffish->fish_ref = item; + return 1; + } + } + + return 0; +} static int match_conversion (Babl *conversion, @@ -47,6 +128,20 @@ babl_conversion_find (const void *source, return data; } +int +babl_fish_get_id (const Babl *source, + const Babl *destination) +{ + /* value of 'id' will be used as argument for hash function, + * substraction serves as simple combination of + * source/destination values. */ + int id = (int) source - (int) destination; + /* instances with id 0 won't be inserted into database */ + if (id == 0) + id = 1; + return id; +} + BablDb * babl_fish_db (void) { @@ -55,28 +150,6 @@ babl_fish_db (void) return db; } -static inline Babl * -go_fishing (const Babl *source, - const Babl *destination) -{ - BablDb *db = babl_fish_db (); - int i; - - for (i = 0; i < db->babl_list->count; i++) - { - Babl *item = db->babl_list->items[i]; - if ((void *) source == (void *) item->fish.source && - (void *) destination == (void *) item->fish.destination && - (item->class_type == BABL_FISH_PATH || /* accept only paths */ - source == destination) /* or memcpy */ - ) - { - return item; - } - } - return NULL; -} - Babl * babl_fish (const void *source, const void *destination, @@ -89,14 +162,10 @@ babl_fish (const void *source, babl_assert (destination); if (BABL_IS_BABL (source)) - { - source_format = source; - } + source_format = source; if (!source_format) - { - source_format = babl_format ((char *) source); - } + source_format = babl_format ((char *) source); if (!source_format) { @@ -105,14 +174,10 @@ babl_fish (const void *source, } if (BABL_IS_BABL (destination)) - { - destination_format = destination; - } + destination_format = destination; if (!destination_format) - { - destination_format = babl_format ((char *) destination); - } + destination_format = babl_format ((char *) destination); if (!destination_format) { @@ -121,41 +186,90 @@ babl_fish (const void *source, } { - Babl *lucky; - lucky = go_fishing (source_format, destination_format); - if (lucky) - return lucky; - } + int hashval; + BablHashTable *id_htable; + BablFindFish ffish = {(Babl *) NULL, + (Babl *) NULL, + (Babl *) NULL, + 0, + source_format, + destination_format}; - if (0) /* do not accept shortcut conversions, since there might be - a faster path, besides the shortcut conversion might - have a too large error, let's rely on the paths for - error checking. - */ - { - Babl *shortcut_conversion; + id_htable = (babl_fish_db ())->id_hash; + hashval = babl_hash_by_int (id_htable, babl_fish_get_id (source_format, destination_format)); - shortcut_conversion = babl_conversion_find ( - source_format, destination_format); - - if (shortcut_conversion) - { - return babl_fish_simple (&(shortcut_conversion->conversion)); - } - } + if (source_format == destination_format) + { + /* In the case of equal source and destination formats + * we will search through the fish database for reference fish + * to handle the memcpy */ + id_htable->find_func = find_memcpy_fish; + babl_hash_table_find (id_htable, hashval, (void *) &ffish); + } + else + { + /* In the case of different source and destination formats + * we will search through the fish database for appropriate fish path + * to handle the conversion. In the case that preexistent + * fish path is found, we'll return it. In the case BABL_FISH + * instance with the same source/destination is found, we'll + * return reference fish. + * In the case neither fish path nor BABL_FISH path are found, + * we'll try to construct new fish path for requested + * source/destination. In the case new fish path is found, we'll + * return it, otherwise we'll create dummy BABL_FISH instance and + * insert it into the fish database to indicate non-existent fish + * path. + */ + id_htable->find_func = find_fish_path; + babl_hash_table_find (id_htable, hashval, (void *) &ffish); - { - Babl *fish_path; + if (ffish.fish_path) + { + /* we have found suitable fish path in the database */ + return ffish.fish_path; + } + if (!ffish.fish_fish) + { + /* we haven't tried to search for suitable path yet */ + Babl *fish_path = babl_fish_path (source_format, destination_format); - fish_path = babl_fish_path (source_format, destination_format); + if (fish_path) + { + return fish_path; + } + else + { + /* there isn't a suitable path for requested formats, + * let's create a dummy BABL_FISH instance and insert + * it into the fish database to indicate that such path + * does not exist. + */ + char *name = "X"; /* name does not matter */ + Babl *fish = babl_calloc (1, sizeof (BablFish) + strlen (name) + 1); + + fish->class_type = BABL_FISH; + fish->instance.id = babl_fish_get_id (source_format, destination_format); + fish->instance.name = ((char *) fish) + sizeof (BablFish); + strcpy (fish->instance.name, name); + fish->fish.source = source_format; + fish->fish.destination = destination_format; + babl_db_insert (babl_fish_db (), fish); + } + } + } - if (fish_path) + if (ffish.fish_ref) + { + /* we have already found suitable reference fish */ + return ffish.fish_ref; + } + else { - return fish_path; + /* we have to create new reference fish */ + return babl_fish_reference (source_format, destination_format); } } - - return babl_fish_reference (source_format, destination_format); } long @@ -164,7 +278,7 @@ babl_fish_process (Babl *babl, void *destination, long n) { - long ret = 0; + long ret = 0; switch (babl->class_type) { diff --git a/babl/babl-internal.h b/babl/babl-internal.h index 72d6a79..1d0e281 100644 --- a/babl/babl-internal.h +++ b/babl/babl-internal.h @@ -88,6 +88,8 @@ long babl_fish_path_process (Babl *babl, void *source, void *destination, long n); +int babl_fish_get_id (const Babl *source, + const Babl *destination); double babl_format_loss (Babl *babl); Babl * babl_image_from_linear (char *buffer, -- 2.30.2